package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"gitee.com/wangshh_123/cross-pay-go/src/utils/common"
)

func main() {
	log.Println("🔍 开始检测项目中的精度问题...")

	detector := common.NewPrecisionDetector()

	// 检测项目根目录
	projectRoot := "."
	if err := scanProject(projectRoot, detector); err != nil {
		log.Fatalf("扫描项目失败: %v", err)
	}

	// 运行精度测试
	detector.TestPrecisionLoss()

	// 生成报告
	report := detector.GenerateReport()
	fmt.Println(report)

	// 保存报告到文件
	if err := saveReport(report); err != nil {
		log.Printf("保存报告失败: %v", err)
	}
}

func scanProject(root string, detector *common.PrecisionDetector) error {
	return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 跳过隐藏目录和文件
		if info.IsDir() {
			if strings.HasPrefix(info.Name(), ".") ||
				info.Name() == "vendor" ||
				info.Name() == "node_modules" ||
				info.Name() == "tmp" ||
				info.Name() == "scripts" {
				return filepath.SkipDir
			}
			return nil
		}

		// 只处理 Go 文件
		if !strings.HasSuffix(path, ".go") {
			return nil
		}

		// 跳过测试文件
		if strings.Contains(path, "_test.go") {
			return nil
		}

		// 读取文件内容
		content, err := os.ReadFile(path)
		if err != nil {
			log.Printf("读取文件失败 %s: %v", path, err)
			return nil
		}

		contentStr := string(content)

		// 检测精度问题
		detectInexactFloat64Usage(contentStr, path, detector)
		detectFloat64Conversion(contentStr, path, detector)
		detectFloat64AmountFields(contentStr, path, detector)

		return nil
	})
}

func detectInexactFloat64Usage(content, filePath string, detector *common.PrecisionDetector) {
	lines := strings.Split(content, "\n")
	for i, line := range lines {
		if strings.Contains(line, "InexactFloat64()") {
			detector.Issues = append(detector.Issues, common.PrecisionIssue{
				File:        filePath,
				Line:        i + 1,
				Type:        "InexactFloat64",
				Description: "使用 InexactFloat64() 可能导致精度损失",
				Severity:    "HIGH",
				Fix:         "使用 FormatDecimal() 或 String() 方法保持精度",
			})
		}
	}
}

func detectFloat64Conversion(content, filePath string, detector *common.PrecisionDetector) {
	lines := strings.Split(content, "\n")
	for i, line := range lines {
		if strings.Contains(line, ".Float64()") {
			detector.Issues = append(detector.Issues, common.PrecisionIssue{
				File:        filePath,
				Line:        i + 1,
				Type:        "Float64",
				Description: "使用 Float64() 可能导致精度损失",
				Severity:    "MEDIUM",
				Fix:         "使用 FormatDecimal() 或 String() 方法保持精度",
			})
		}
	}
}

func detectFloat64AmountFields(content, filePath string, detector *common.PrecisionDetector) {
	lines := strings.Split(content, "\n")
	for i, line := range lines {
		lineLower := strings.ToLower(line)
		if strings.Contains(line, "float64") &&
			(strings.Contains(lineLower, "amount") ||
				strings.Contains(lineLower, "balance") ||
				strings.Contains(lineLower, "fee") ||
				strings.Contains(lineLower, "total") ||
				strings.Contains(lineLower, "price") ||
				strings.Contains(lineLower, "cost")) {
			detector.Issues = append(detector.Issues, common.PrecisionIssue{
				File:        filePath,
				Line:        i + 1,
				Type:        "Float64Amount",
				Description: "金额字段使用 float64 类型，可能导致精度损失",
				Severity:    "HIGH",
				Fix:         "将字段类型改为 decimal.Decimal",
			})
		}
	}
}

func saveReport(report string) error {
	// 确保 scripts 目录存在
	if err := os.MkdirAll("scripts", 0755); err != nil {
		return err
	}

	// 保存报告到文件
	reportFile := "scripts/precision_report.txt"
	if err := os.WriteFile(reportFile, []byte(report), 0644); err != nil {
		return err
	}

	log.Printf("📄 精度检测报告已保存到: %s", reportFile)
	return nil
}
